#ifndef _WX_RICHTEXTSTYLES_H_
#define _WX_RICHTEXTSTYLES_H_

#include "wx/defs.h"
#include "wx/richtext/richtextbuffer.h"
#include <wx/htmllbox.h>
#include "wx/combo.h"
#include "wx/choice.h"

class wxRichTextCtrl;
class wxRichTextBuffer;

class wxRichTextStyleDefinition: public wxObject {
    DECLARE_CLASS( wxRichTextStyleDefinition )
  public:
    wxRichTextStyleDefinition( const wxRichTextStyleDefinition& def )
      : wxObject() {
      Init();
      Copy( def );
    }
    wxRichTextStyleDefinition( const wxString& name = wxEmptyString ) { Init(); m_name = name; }


    virtual ~wxRichTextStyleDefinition() {}


    void Init() {}


    void Copy( const wxRichTextStyleDefinition& def );


    bool Eq( const wxRichTextStyleDefinition& def ) const;


    void operator =( const wxRichTextStyleDefinition& def ) { Copy( def ); }


    bool operator ==( const wxRichTextStyleDefinition& def ) const { return Eq( def ); }


    virtual wxRichTextStyleDefinition* Clone() const = 0;


    void SetName( const wxString& name ) { m_name = name; }
    const wxString& GetName() const { return m_name; }


    void SetDescription( const wxString& descr ) { m_description = descr; }
    const wxString& GetDescription() const { return m_description; }


    void SetBaseStyle( const wxString& name ) { m_baseStyle = name; }
    const wxString& GetBaseStyle() const { return m_baseStyle; }


    void SetStyle( const wxRichTextAttr& style ) { m_style = style; }
    const wxRichTextAttr& GetStyle() const { return m_style; }
    wxRichTextAttr& GetStyle() { return m_style; }


    virtual wxRichTextAttr GetStyleMergedWithBase( const wxRichTextStyleSheet* sheet ) const;

  protected:
    wxString        m_name;
    wxString        m_baseStyle;
    wxString        m_description;
    wxRichTextAttr  m_style;
};

class wxRichTextCharacterStyleDefinition: public wxRichTextStyleDefinition {
    DECLARE_DYNAMIC_CLASS( wxRichTextCharacterStyleDefinition )
  public:


    wxRichTextCharacterStyleDefinition( const wxRichTextCharacterStyleDefinition& def ): wxRichTextStyleDefinition( def ) {}


    wxRichTextCharacterStyleDefinition( const wxString& name = wxEmptyString ):
      wxRichTextStyleDefinition( name ) {}


    virtual ~wxRichTextCharacterStyleDefinition() {}


    virtual wxRichTextStyleDefinition* Clone() const { return new wxRichTextCharacterStyleDefinition( *this ); }

  protected:
};

/*!
  wxRichTextParagraphStyleDefinition class declaration
*/

class wxRichTextParagraphStyleDefinition: public wxRichTextStyleDefinition {
    DECLARE_DYNAMIC_CLASS( wxRichTextParagraphStyleDefinition )
  public:


    wxRichTextParagraphStyleDefinition( const wxRichTextParagraphStyleDefinition& def ): wxRichTextStyleDefinition( def ) { m_nextStyle = def.m_nextStyle; }


    wxRichTextParagraphStyleDefinition( const wxString& name = wxEmptyString ):
      wxRichTextStyleDefinition( name ) {}


    virtual ~wxRichTextParagraphStyleDefinition() {}


    void SetNextStyle( const wxString& name ) { m_nextStyle = name; }
    const wxString& GetNextStyle() const { return m_nextStyle; }


    void Copy( const wxRichTextParagraphStyleDefinition& def );


    void operator =( const wxRichTextParagraphStyleDefinition& def ) { Copy( def ); }


    bool operator ==( const wxRichTextParagraphStyleDefinition& def ) const;


    virtual wxRichTextStyleDefinition* Clone() const { return new wxRichTextParagraphStyleDefinition( *this ); }

  protected:


    wxString    m_nextStyle;
};

class wxRichTextListStyleDefinition: public wxRichTextParagraphStyleDefinition {
    DECLARE_DYNAMIC_CLASS( wxRichTextListStyleDefinition )
  public:


    wxRichTextListStyleDefinition( const wxRichTextListStyleDefinition& def ): wxRichTextParagraphStyleDefinition( def ) { Init(); Copy( def ); }


    wxRichTextListStyleDefinition( const wxString& name = wxEmptyString ):
      wxRichTextParagraphStyleDefinition( name ) { Init(); }


    virtual ~wxRichTextListStyleDefinition() {}


    void Copy( const wxRichTextListStyleDefinition& def );


    void operator =( const wxRichTextListStyleDefinition& def ) { Copy( def ); }


    bool operator ==( const wxRichTextListStyleDefinition& def ) const;


    virtual wxRichTextStyleDefinition* Clone() const { return new wxRichTextListStyleDefinition( *this ); }


    void SetLevelAttributes( int i, const wxRichTextAttr& attr );
    wxRichTextAttr* GetLevelAttributes( int i );
    const wxRichTextAttr* GetLevelAttributes( int i ) const;


    void SetAttributes( int i, int leftIndent, int leftSubIndent, int bulletStyle, const wxString& bulletSymbol = wxEmptyString );


    int FindLevelForIndent( int indent ) const;



    wxRichTextAttr CombineWithParagraphStyle( int indent, const wxRichTextAttr& paraStyle, wxRichTextStyleSheet* styleSheet = NULL );



    wxRichTextAttr GetCombinedStyle( int indent, wxRichTextStyleSheet* styleSheet = NULL );



    wxRichTextAttr GetCombinedStyleForLevel( int level, wxRichTextStyleSheet* styleSheet = NULL );


    int GetLevelCount() const { return 10; }


    bool IsNumbered( int i ) const;

  protected:


    wxRichTextAttr m_levelStyles[10];
};

class wxRichTextStyleSheet: public wxObject {
    DECLARE_CLASS( wxRichTextStyleSheet )

  public:

    wxRichTextStyleSheet( const wxRichTextStyleSheet& sheet )
      : wxObject() {
      Init();
      Copy( sheet );
    }
    wxRichTextStyleSheet() { Init(); }
    virtual ~wxRichTextStyleSheet();


    void Init();


    void Copy( const wxRichTextStyleSheet& sheet );


    void operator=( const wxRichTextStyleSheet& sheet ) { Copy( sheet ); }


    bool operator==( const wxRichTextStyleSheet& sheet ) const;


    bool AddCharacterStyle( wxRichTextCharacterStyleDefinition* def );


    bool AddParagraphStyle( wxRichTextParagraphStyleDefinition* def );


    bool AddListStyle( wxRichTextListStyleDefinition* def );


    bool AddStyle( wxRichTextStyleDefinition* def );


    bool RemoveCharacterStyle( wxRichTextStyleDefinition* def, bool deleteStyle = false ) { return RemoveStyle( m_characterStyleDefinitions, def, deleteStyle ); }


    bool RemoveParagraphStyle( wxRichTextStyleDefinition* def, bool deleteStyle = false ) { return RemoveStyle( m_paragraphStyleDefinitions, def, deleteStyle ); }


    bool RemoveListStyle( wxRichTextStyleDefinition* def, bool deleteStyle = false ) { return RemoveStyle( m_listStyleDefinitions, def, deleteStyle ); }


    bool RemoveStyle( wxRichTextStyleDefinition* def, bool deleteStyle = false );


    wxRichTextCharacterStyleDefinition* FindCharacterStyle( const wxString& name, bool recurse = true ) const { return ( wxRichTextCharacterStyleDefinition* ) FindStyle( m_characterStyleDefinitions, name, recurse ); }


    wxRichTextParagraphStyleDefinition* FindParagraphStyle( const wxString& name, bool recurse = true ) const { return ( wxRichTextParagraphStyleDefinition* ) FindStyle( m_paragraphStyleDefinitions, name, recurse ); }


    wxRichTextListStyleDefinition* FindListStyle( const wxString& name, bool recurse = true ) const { return ( wxRichTextListStyleDefinition* ) FindStyle( m_listStyleDefinitions, name, recurse ); }


    wxRichTextStyleDefinition* FindStyle( const wxString& name, bool recurse = true ) const;


    size_t GetCharacterStyleCount() const { return m_characterStyleDefinitions.GetCount(); }


    size_t GetParagraphStyleCount() const { return m_paragraphStyleDefinitions.GetCount(); }


    size_t GetListStyleCount() const { return m_listStyleDefinitions.GetCount(); }


    wxRichTextCharacterStyleDefinition* GetCharacterStyle( size_t n ) const { return ( wxRichTextCharacterStyleDefinition* ) m_characterStyleDefinitions.Item( n )->GetData(); }


    wxRichTextParagraphStyleDefinition* GetParagraphStyle( size_t n ) const { return ( wxRichTextParagraphStyleDefinition* ) m_paragraphStyleDefinitions.Item( n )->GetData(); }


    wxRichTextListStyleDefinition* GetListStyle( size_t n ) const { return ( wxRichTextListStyleDefinition* ) m_listStyleDefinitions.Item( n )->GetData(); }


    void DeleteStyles();


    bool InsertSheet( wxRichTextStyleSheet* before );


    bool AppendSheet( wxRichTextStyleSheet* after );


    void Unlink();


    wxRichTextStyleSheet* GetNextSheet() const { return m_nextSheet; }
    void SetNextSheet( wxRichTextStyleSheet* sheet ) { m_nextSheet = sheet; }


    wxRichTextStyleSheet* GetPreviousSheet() const { return m_previousSheet; }
    void SetPreviousSheet( wxRichTextStyleSheet* sheet ) { m_previousSheet = sheet; }


    void SetName( const wxString& name ) { m_name = name; }
    const wxString& GetName() const { return m_name; }


    void SetDescription( const wxString& descr ) { m_description = descr; }
    const wxString& GetDescription() const { return m_description; }




    bool AddStyle( wxList& list, wxRichTextStyleDefinition* def );


    bool RemoveStyle( wxList& list, wxRichTextStyleDefinition* def, bool deleteStyle );


    wxRichTextStyleDefinition* FindStyle( const wxList& list, const wxString& name, bool recurse = true ) const;

  protected:

    wxString                m_description;
    wxString                m_name;

    wxList                  m_characterStyleDefinitions;
    wxList                  m_paragraphStyleDefinitions;
    wxList                  m_listStyleDefinitions;

    wxRichTextStyleSheet*   m_previousSheet;
    wxRichTextStyleSheet*   m_nextSheet;
};

class  wxRichTextStyleListBox: public wxHtmlListBox {
    DECLARE_CLASS( wxRichTextStyleListBox )
    DECLARE_EVENT_TABLE()
  public:
    enum wxRichTextStyleType {
      wxRICHTEXT_STYLE_ALL,
      wxRICHTEXT_STYLE_PARAGRAPH,
      wxRICHTEXT_STYLE_CHARACTER,
      wxRICHTEXT_STYLE_LIST
    };

    wxRichTextStyleListBox() {
      Init();
    }
    wxRichTextStyleListBox( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                            const wxSize& size = wxDefaultSize, long style = 0 );
    virtual ~wxRichTextStyleListBox();

    void Init() {
      m_styleSheet = NULL;
      m_richTextCtrl = NULL;
      m_applyOnSelection = false;
      m_styleType = wxRICHTEXT_STYLE_PARAGRAPH;
      m_autoSetSelection = true;
    }

    bool Create( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize, long style = 0 );


    wxString CreateHTML( wxRichTextStyleDefinition* def ) const;


    void SetStyleSheet( wxRichTextStyleSheet* styleSheet ) { m_styleSheet = styleSheet; }
    wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }


    void SetRichTextCtrl( wxRichTextCtrl* ctrl ) { m_richTextCtrl = ctrl; }
    wxRichTextCtrl* GetRichTextCtrl() const { return m_richTextCtrl; }


    wxRichTextStyleDefinition* GetStyle( size_t i ) const ;


    int GetIndexForStyle( const wxString& name ) const ;


    int SetStyleSelection( const wxString& name );


    void UpdateStyles();


    void ApplyStyle( int i );


    void OnLeftDown( wxMouseEvent& event );


    void OnLeftDoubleClick( wxMouseEvent& event );


    void OnIdle( wxIdleEvent& event );


    int ConvertTenthsMMToPixels( wxDC& dc, int units ) const;



    virtual bool CanAutoSetSelection() { return m_autoSetSelection; }
    virtual void SetAutoSetSelection( bool autoSet ) { m_autoSetSelection = autoSet; }


    void SetApplyOnSelection( bool applyOnSel ) { m_applyOnSelection = applyOnSel; }
    bool GetApplyOnSelection() const { return m_applyOnSelection; }


    void SetStyleType( wxRichTextStyleType styleType ) { m_styleType = styleType; UpdateStyles(); }
    wxRichTextStyleType GetStyleType() const { return m_styleType; }


    static wxString GetStyleToShowInIdleTime( wxRichTextCtrl* ctrl, wxRichTextStyleType styleType );

  protected:

    virtual wxString OnGetItem( size_t n ) const;

  private:

    wxRichTextStyleSheet*   m_styleSheet;
    wxRichTextCtrl*         m_richTextCtrl;
    bool                    m_applyOnSelection;
    wxRichTextStyleType     m_styleType;
    bool                    m_autoSetSelection;
    wxArrayString           m_styleNames;
};

#define wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR     0x1000

class wxRichTextStyleListCtrl: public wxControl {
    DECLARE_CLASS( wxRichTextStyleListCtrl )
    DECLARE_EVENT_TABLE()

  public:


    wxRichTextStyleListCtrl() {
      Init();
    }

    wxRichTextStyleListCtrl( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                             const wxSize& size = wxDefaultSize, long style = 0 );


    virtual ~wxRichTextStyleListCtrl();


    void Init() {
      m_styleListBox = NULL;
      m_styleChoice = NULL;
      m_dontUpdate = false;
    }


    bool Create( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize, long style = 0 );


    void UpdateStyles();


    void SetStyleSheet( wxRichTextStyleSheet* styleSheet );
    wxRichTextStyleSheet* GetStyleSheet() const;


    void SetRichTextCtrl( wxRichTextCtrl* ctrl );
    wxRichTextCtrl* GetRichTextCtrl() const;


    void SetStyleType( wxRichTextStyleListBox::wxRichTextStyleType styleType );
    wxRichTextStyleListBox::wxRichTextStyleType GetStyleType() const;


    int StyleTypeToIndex( wxRichTextStyleListBox::wxRichTextStyleType styleType );


    wxRichTextStyleListBox::wxRichTextStyleType StyleIndexToType( int i );


    wxRichTextStyleListBox* GetStyleListBox() const { return m_styleListBox; }


    wxChoice* GetStyleChoice() const { return m_styleChoice; }


    void OnChooseType( wxCommandEvent& event );


    void OnSize( wxSizeEvent& event );

  private:

    wxRichTextStyleListBox* m_styleListBox;
    wxChoice*               m_styleChoice;
    bool                    m_dontUpdate;
};

class wxRichTextStyleComboPopup : public wxRichTextStyleListBox, public wxComboPopup {
  public:
    virtual void Init() {
      m_itemHere = -1;
      m_value = -1;
    }

    virtual bool Create( wxWindow* parent ) {
      return wxRichTextStyleListBox::Create( parent, wxID_ANY, wxPoint( 0, 0 ), wxDefaultSize, wxSIMPLE_BORDER );
    }

    virtual wxWindow *GetControl() { return this; }
    virtual void SetStringValue( const wxString& s );
    virtual wxString GetStringValue() const;
    virtual bool CanAutoSetSelection() { return false; }
    void OnMouseMove( wxMouseEvent& event );


    void OnMouseClick( wxMouseEvent & ( event ) );

  protected:

    int             m_itemHere;
    int             m_value;

  private:
    DECLARE_EVENT_TABLE()
};

class wxRichTextStyleComboCtrl: public wxComboCtrl {
    DECLARE_CLASS( wxRichTextStyleComboCtrl )
    DECLARE_EVENT_TABLE()

  public:
    wxRichTextStyleComboCtrl() {
      Init();
    }

    wxRichTextStyleComboCtrl( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                              const wxSize& size = wxDefaultSize, long style = wxCB_READONLY ) {
      Init();
      Create( parent, id, pos, size, style );
    }

    virtual ~wxRichTextStyleComboCtrl() {}

    void Init() {
      m_stylePopup = NULL;
    }

    bool Create( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize, long style = 0 );


    void UpdateStyles() { m_stylePopup->UpdateStyles(); }
    void SetStyleSheet( wxRichTextStyleSheet* styleSheet ) { m_stylePopup->SetStyleSheet( styleSheet ); }
    wxRichTextStyleSheet* GetStyleSheet() const { return m_stylePopup->GetStyleSheet(); }
    void SetRichTextCtrl( wxRichTextCtrl* ctrl ) { m_stylePopup->SetRichTextCtrl( ctrl ); }
    wxRichTextCtrl* GetRichTextCtrl() const { return m_stylePopup->GetRichTextCtrl(); }
    wxRichTextStyleComboPopup* GetStylePopup() const { return m_stylePopup; }
    void OnIdle( wxIdleEvent& event );

  protected:
    wxRichTextStyleComboPopup*  m_stylePopup;
};

#endif
